package com.onlygx.dva.web.ui.service;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONUtil;
import com.onlygx.dva.config.annotation.security.AuthNorm;
import com.onlygx.dva.config.constant.PermsKeyConstant;
import com.onlygx.dva.redis.service.RedisService;
import com.onlygx.dva.utils.AuthUtils;
import com.onlygx.dva.web.ui.entity.BaseRole;
import com.onlygx.dva.web.ui.entity.dto.BaseRoleSearchDTO;
import com.onlygx.dva.web.ui.entity.vo.BaseRoleShowVO;
import com.onlygx.dva.web.ui.mapper.BaseRoleMapper;
import com.baomidou.mybatisplus.extension.service.IService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import lombok.RequiredArgsConstructor;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.List;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

/**
 * <p>
 * 角色表 服务实现类
 * </p>
 *
 * @author GaoXiang
 * @since 2023-08-04
 * @version V1.0
 */
@Service
@RequiredArgsConstructor
public class BaseRoleService extends ServiceImpl<BaseRoleMapper, BaseRole> implements IService<BaseRole>{

    final BaseRoleMapper baseRoleMapper;

    final RedisService redisService;

    public Page<BaseRoleShowVO> pageByParam(Page<BaseRoleSearchDTO> page, BaseRoleSearchDTO param) {

        return baseRoleMapper.pageByParam(page,param);
    }

    /**
     * 获取当前用户所有角色
     * 2023年8月4日15:03:31 高祥
     */
    public List<BaseRole> selectByUserId(String userId){

        return baseRoleMapper.selectByUserId(userId);
    }

    public List<String> selectCodeByUserId(String userId){

        List<BaseRole> roleList = selectByUserId(userId);

        return roleList.stream().map(BaseRole::getCode).collect(Collectors.toList());
    }

    /**
     * 获取用户角色缓存
     * 缓存有效期十分钟，如果获取不到，则会调用数据库查询并重新缓存
     * 2023年8月8日10:28:23 高祥。
     */
    public List<String> selectUserRoleCache(String userId){
        String userRolesCacheJsonStr = (String) redisService.get(PermsKeyConstant.USER_ROLES + userId);
        if(StrUtil.isEmpty(userRolesCacheJsonStr)){
            //log.info("查询用户角色，缓存未命中。");
            List<String> permList = selectCodeByUserId(userId);
            //如果当前用户没有角色信息，直接返回 false
            if(CollectionUtil.isEmpty(permList)){ return null; }
            //缓存当前用户角色信息
            //注意：如果其它地方修改了用户角色，记得维护redis缓存。
            //可调用 当前service中的 refreshUserRoleCache 方法刷新
            redisService.set(PermsKeyConstant.USER_ROLES + userId
                    , JSONUtil.toJsonStr(permList),10, TimeUnit.MINUTES);
            return permList;
        }
        //log.info("查询用户角色，缓存命中。");
        return JSONUtil.toList(userRolesCacheJsonStr,String.class);
    }

    /**
     * 刷新用户角色缓存信息
     * 强制获取最新角色更新redis缓存。
     * 2023年8月8日10:32:46 高祥
     */
    public void refreshUserRolesCache(String userId){
        List<String> roleList = selectCodeByUserId(userId);
        //如果当前用户没有权限信息，直接返回
        if(CollectionUtil.isEmpty(roleList)){ return; }
        //缓存当前用户权限信息
        redisService.set(PermsKeyConstant.USER_ROLES + userId
                , JSONUtil.toJsonStr(roleList),10, TimeUnit.MINUTES);
    }

    /**
     * 判断指定ID的用户是否具有指定角色
     * @param userId 用户id
     * @param perms 指定角色列表
     * @param authNorm 判断逻辑 or或者and
     * @return 判断结果
     */
    public boolean judgeRoles(String userId, List<String> perms, AuthNorm authNorm){
        List<String> userRoles = selectUserRoleCache(userId);
        return AuthUtils.judgeAuth(perms, authNorm, userRoles);
    }


}
